package frames;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

/** Implements a tree to view and edit 
 * the databases and tables
 * 
 * @author Konstantin Dobrev
 * @version 1.0
 *
 */
public class DatabaseTree extends JTree {
	
	private Connection dbConnection;
	private DefaultMutableTreeNode root;
	
	/** Constructor for class
	 * 
	 * @param frame references the main program frame
	 * in order to add items to it
	 */
	DatabaseTree(ProgramFrame frame) {
		super(new DefaultMutableTreeNode("Databases"));
		root = (DefaultMutableTreeNode) this.getModel().getRoot();
		
		this.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		this.addMouseListener((new DBTreeMouseListener(this)));
	}

	/**
	 * Closes an active database connection and
	 * removes DB information from the tree
	 */
	public void removeConnDatabases() {
		DefaultTreeModel model = (DefaultTreeModel) this.getModel();
		root = new DefaultMutableTreeNode("Databases");
		model.setRoot(root);
		dbConnection = null;
	}
	
	/** Stores connection data and Initializes the tree with it
	 * 
	 * @param conn references the established connection
	 * @exception SQLException
	 */
	public void setConnDatabases(Connection conn) {
		dbConnection = conn;
		ResultSet nodeNames = null;
		try {
			Statement getNodesStm = dbConnection.createStatement();
			nodeNames = getNodesStm.executeQuery("SHOW DATABASES");
			while(nodeNames.next()) {
				String dbName = nodeNames.getString(1);
				DefaultMutableTreeNode dbNode = new DefaultMutableTreeNode(dbName);
				root.add(dbNode);
			}
		}
		catch (SQLException ex) {
			JOptionPane.showMessageDialog(null, ex.getMessage());
		}
	}
	
	/** Implements a listener in order to manage databases and tables
	 * 
	 * @author Konstantin Dobrev
	 * @version 1.0
	 */
	private class DBTreeMouseListener implements MouseListener {

		DatabaseTree dbTree;
		
		/** Class constructor
		 * 
		 * @param tree keeps a reference to the caller object
		 * in order to change it's structure
		 */
		DBTreeMouseListener(DatabaseTree tree) {
			dbTree = tree;
		}
		
		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			int clickPosition = dbTree.getRowForLocation(e.getX(), e.getY());
			if(clickPosition == -1 || dbConnection == null) return;
			TreePath pathToNode = dbTree.getPathForLocation(e.getX(), e.getY());
			if(e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
				if(pathToNode.getPathCount() == 2) {
					try {
						DefaultMutableTreeNode nodeFromPath = (DefaultMutableTreeNode) pathToNode.getLastPathComponent();
						if(nodeFromPath.getChildCount() != 0) return;
						Statement stm = dbConnection.createStatement();
						stm.execute("USE " + pathToNode.getLastPathComponent());
						ResultSet tables = stm.executeQuery("SHOW TABLES");
						while(tables.next()) {
							DefaultMutableTreeNode tableNode = new DefaultMutableTreeNode(tables.getString(1));
							nodeFromPath.add(tableNode);
						}
					} catch (SQLException ex) {
						JOptionPane.showMessageDialog(null, ex.getMessage());
					}
				}
			}
			else if(e.getButton() == MouseEvent.BUTTON3) {
				JPopupMenu menu = null;
				switch(pathToNode.getPathCount()) {
				case 1: menu = new DBMSMenu(dbTree, dbConnection); break;
				case 2: menu = new DBMenu(dbTree, pathToNode, dbConnection); break;
				case 3: menu = new TableMenu(dbTree, pathToNode, dbConnection);
				}
				menu.show(dbTree, e.getX(), e.getY());
			}
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}
	}
	
	

}
